package com.cyy;

/**
 * @author 会玩的洋洋
 * @since 2022-02-22
 * @param <E>
 *
 * 循环双端队列：可以进行两端添加、删除操作的循环队列
 */
public class CircleDeque<E> {
    /**
     * 队头下标
     */
    private int frontIndex;
    /**
     * 元素个数
     */
    private int size;
    /**
     * 存储元素
     */
    private E[] elements;
    /**
     * 默认队列容量大小
     */
    private final static int DEFAULT_CAPACITY = 10;

    public CircleDeque() {
        this(DEFAULT_CAPACITY);
    }

    public CircleDeque(int capacity) {
        elements = (E[])new Object[Math.max(capacity, DEFAULT_CAPACITY)];
        size = 0;
    }

    /**
     * 元素个数
     * @return int
     */
    public int size() {
        return size;
    }

    /**
     * 判断队列是否为空
     * @return boolean
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 队尾插入
     * @param element 插入元素
     */
    public void enQueueRear(E element) {
        ensureCapacity(size + 1);
        elements[index(size)] = element;
        size++;
    }

    /**
     * 队头出队
     * @return E
     */
    public E deQueueFront() {
        E oldElement = elements[frontIndex];
        elements[frontIndex] = null;
        frontIndex = index(1);
        size--;
        return oldElement;
    }

    public void enQueueFront(E element) {
        ensureCapacity(size + 1);
        frontIndex = index(-1);
        elements[frontIndex] = element;
        size++;
    }

    /**
     * 删除队尾元素
     * @return E
     */
    public E deQueueRear() {
        int rear = index(size - 1);
        E oldElement = elements[rear];
        elements[rear] = null;
        --size;
        return oldElement;
    }

    public E front() {
        return elements[frontIndex];
    }

    public E rear() {
        return elements[index(size - 1)];
    }

    public void clear() {
        for (int i = 0; i < size; i++) {
            elements[index(i)] = null;
        }
        frontIndex = 0;
        size = 0;
    }

    private int index(int index) {
        index += frontIndex;
        if (index < 0) {
            return index + elements.length;
        }
        return index - (index >= elements.length ? elements.length : 0);
    }

    /**
     * 扩容操作
     * @param capacity 当前传入容器大小
     */
    private void ensureCapacity(int capacity) {
        int oldCapacity = elements.length;
        if (capacity <= oldCapacity) {
            return;
        }

        // 扩容 深度 copy 扩容为原来的 1.5 倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        E[] newElements = (E[])new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newElements[i] = elements[index(i)];
        }

        elements = newElements;
        frontIndex = 0;
    }

    @Override
    public String toString() {
        StringBuilder string = new StringBuilder();
        string.append("capcacity=").append(elements.length)
                .append(" size=").append(size)
                .append(" front=").append(frontIndex)
                .append(", [");
        for (int i = 0; i < elements.length; i++) {
            if (i != 0) {
                string.append(", ");
            }

            string.append(elements[i]);
        }
        string.append("]");
        return string.toString();
    }
}
